home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * graygrad.c - Convert DCTV gradient to 4-bit gray screen.
- *
- * Copyright (C) 1992 Digital Creations, Inc.
- *
- * DESCRIPTION
- * This example demonstrates how to call dctv.library to convert
- * a DCTV display BitMap to 24-bit RGB. The source DCTV BitMap
- * is a gradient generated in the same manner as in dctvgrad.c.
- * This DCTV image is then converted line by line to 24-bit RGB.
- * Then the upper 4 bits of the blue component are displayed on
- * a 16-color hires screen.
- *
- * (not particularly flashy, but at least you get to see something).
- *
- * Program runs under Amiga OS v1.3 and higher.
- *
- * USAGE
- * graygrad <width> <height> <depth>
- * width - screen width (640..736)
- * height - screen height (200..241, 400..482)
- * depth - screen depth (3..4)
- *
- * Terminate with Control+C.
- *
- * COMPILATION
- * SAS/C: (v5.10 or higher. Regular of ANSI libs)
- * lc -L+dctv.lib graygrad
- *
- * Aztec C: (v5.0a or higher)
- * cc graygrad [works w/ either 16 or 32 bit int's]
- * ln graygrad.o +l dctv.lib -lc
- *
- * REQUIREMENTS
- * . Aztec C 5.0 or SAS/C 5.10.
- * . v37.4 or higher Amiga include files.
- * . OS #pragmas created for your compiler in the pragmas
- * directory of your include path.
- *
- **********************************************************************/
-
- #include <dos/dos.h>
- #include <exec/memory.h>
- #include <intuition/screens.h>
- #include <libraries/dctv.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <clib/dctv_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/graphics_protos.h>
- #include <clib/intuition_protos.h>
-
- #include <pragmas/dctv_pragmas.h>
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/graphics_pragmas.h>
- #include <pragmas/intuition_pragmas.h>
-
-
- /* -------------------- misc defines */
-
- #define DCTVLIB_Version 3
- #define READPIXEL 0 /* selects DCTV->RGB conversion method: set to 1 to use ReadDCTVPixel(), 0 to use CvtDCTVLine() */
-
- #define LaceHeight(height) (height > 350)
-
-
- /* -------------------- data */
-
- struct Library *DCTVBase, *GfxBase, *IntuitionBase;
-
-
- /* -------------------- local functions */
-
- void dograd (short width, short height, short depth);
- BOOL makedctvbm (struct BitMap *dctvbm, UWORD *palette, short width, short height);
- void showgrad (struct BitMap *dctvbm, UWORD *palette, short width, short height);
-
- /* bitmap allocator */
- struct BitMap *allocbm (UWORD width, UWORD height, UBYTE depth);
- void freebm (struct BitMap *);
-
- /* gradient functions */
- void initgrad (struct DCTVCvtHandle *);
- void rendergradline (struct DCTVCvtHandle *);
-
-
- /* -------------------- main() */
-
- #if AZTEC_C
- void _wb_parse (void) {} /* stub out wb window parser */
- #endif
-
- #if __SASC /* suppress normal Ctrl-C processing (SAS/C) */
- void __chkabort (void) {}
- void chkabort (void) {}
- #endif
-
- int main (int argc, char **argv)
- {
- if (argc < 4) goto clean;
-
- #if AZTEC_C /* suppress normal Ctrl-C processing (Aztec C) */
- {
- extern int Enable_Abort;
- Enable_Abort = 0;
- }
- #endif
-
- if (!(IntuitionBase = OpenLibrary ("intuition.library", LIBRARY_MINIMUM))) goto clean;
- if (!(GfxBase = OpenLibrary ("graphics.library", LIBRARY_MINIMUM))) goto clean;
- if (!(DCTVBase = OpenLibrary ("dctv.library", DCTVLIB_Version))) {
- printf ("requires dctv.library v%d\n", DCTVLIB_Version);
- goto clean;
- }
-
- dograd (atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
-
- clean:
- if (DCTVBase) CloseLibrary (DCTVBase);
- if (GfxBase) CloseLibrary (GfxBase);
- if (IntuitionBase) CloseLibrary (IntuitionBase);
- return 0;
- }
-
-
- /* -------------------- dograd() */
-
- void dograd (short width, short height, short depth)
- {
- struct BitMap *dctvbm = NULL;
- UWORD *palette = NULL;
-
- /* pad width to next multiple of 16 */
- width = width + 15 & ~15;
-
- /* allocate a bitmap and palette to hold DCTV display image.
- Notice that this BitMap is not allocated in chip ram as the
- conversions don't require the bitmap to be displayable. */
- if (!(dctvbm = allocbm (width, height, depth)) ||
- !(palette = AllocMem (sizeof (UWORD) << depth, MEMF_ANY | MEMF_CLEAR))) {
- puts ("Out of memory\n");
- goto clean;
- }
-
- /* build DCTV bitmap (draw same gradient as dctvgrad.c) */
- if (!makedctvbm (dctvbm, palette, width, height)) goto clean;
-
- /* convert DCTV display image to a 16-color gray screen of the
- same size as the BitMap */
- showgrad (dctvbm, palette, width, height);
-
- clean:
- if (palette) FreeMem (palette, sizeof (UWORD) << depth);
- if (dctvbm) freebm (dctvbm);
- }
-
-
- /* -------------------- DCTV gradient bitmap builder */
-
- /* this part is pretty much the same as in dctvgrad.c */
-
- BOOL makedctvbm (struct BitMap *dctvbm, UWORD *palette, short width, short height)
- {
- struct DCTVCvtHandle *cvt = NULL;
- ULONG errcode;
- BOOL rtn = FALSE;
-
- puts ("Making gradient.");
-
- /* Allocate DCTV conversion environment. */
- if (!(cvt = AllocDCTVCvtTags ( dctvbm,
- DCTVCVTA_Type, (ULONG)DCTVCVTT_RGBtoDCTV,
- DCTVCVTA_Width, (ULONG)width,
- DCTVCVTA_Height, (ULONG)height,
- DCTVCVTA_Flags, (ULONG)(LaceHeight(height) ? DCTVCVTF_Lace : 0),
- DCTVCVTA_ErrorCode, &errcode,
- TAG_END ))) {
-
- printf ("AllocDCTVCvtTags failed %lu\n", errcode);
- goto clean;
- }
-
- /* copy ColorTable to palette */
- CopyMem (cvt->ColorTable, palette, cvt->NColors * sizeof (UWORD));
-
- /* initialize gradient */
- initgrad (cvt); /* Init gradient data. */
-
- /* Line rendering loop. (See dctvgrad.c for a more complete explanation of this) */
- while (cvt->DstLineNum < cvt->Height) {
-
- /* Abort on Ctrl-C. */
- if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) goto clean;
-
- rendergradline (cvt); /* Render a line of the gradient to
- DCTVCvtHandle RGB line buffer.
- This function is smart enough to
- handle line #'s out of range. */
-
- CvtDCTVLine (cvt); /* Convert the line in the line buffer to
- DCTV display data. Results in rendering
- a line of the BitMap. */
- }
-
- rtn = TRUE;
-
- clean:
- if (cvt) FreeDCTVCvt (cvt);
- return rtn;
- }
-
-
- /* -------------------- gray gradient display */
-
- struct Screen *openscreen (short width, short height);
- BOOL rendergrayscreen (struct Screen *, struct DCTVCvtHandle *);
-
- void showgrad (struct BitMap *dctvbm, UWORD *palette, short width, short height)
- {
- struct Screen *screen = NULL;
- struct DCTVCvtHandle *cvt = NULL;
- ULONG errcode;
-
- puts ("Building Screen.");
-
- if (!(screen = openscreen (width, height))) {
- puts ("openscreen() failed\n");
- goto clean;
- }
-
- if (!(cvt = AllocDCTVCvtTags ( dctvbm,
- DCTVCVTA_Type, (ULONG)DCTVCVTT_DCTVtoRGB,
- DCTVCVTA_Width, (ULONG)width,
- DCTVCVTA_Height, (ULONG)height,
- DCTVCVTA_Flags, (ULONG)(LaceHeight(height) ? DCTVCVTF_Lace : 0),
- DCTVCVTA_ColorTable, palette,
- DCTVCVTA_ErrorCode, &errcode,
- TAG_END ))) {
-
- printf ("AllocDCTVCvtTags() failed %lu\n", errcode);
- goto clean;
- }
-
- if (!rendergrayscreen (screen, cvt)) goto clean;
-
- puts ("Press Ctrl-C");
- Wait (SIGBREAKF_CTRL_C);
-
- clean:
- if (cvt) FreeDCTVCvt (cvt);
- if (screen) CloseScreen (screen);
- }
-
- struct Screen *openscreen (short width, short height)
- {
- static struct NewScreen newscreen = {
- 0, 0, 0, 0, 4,
- -1, -1,
- 0,
- CUSTOMSCREEN | SCREENQUIET,
- NULL,
- "graygrad",
- NULL,
- NULL
- };
- static UWORD palette[] = { /* gray palette */
- 0x000, 0x111, 0x222, 0x333,
- 0x444, 0x555, 0x666, 0x777,
- 0x888, 0x999, 0xaaa, 0xbbb,
- 0xccc, 0xddd, 0xeee, 0xfff
- };
- struct Screen *screen;
-
- newscreen.Width = width;
- newscreen.Height = height;
- newscreen.ViewModes = LaceHeight(height) ? HIRESLACE_KEY : HIRES_KEY;
-
- if (screen = OpenScreen (&newscreen)) {
- LoadRGB4 (&screen->ViewPort, palette, 16);
- }
-
- return screen;
- }
-
- #if READPIXEL
-
- /* display gradient using ReadDCTVPixel() */
-
- BOOL rendergrayscreen (struct Screen *screen, struct DCTVCvtHandle *cvt)
- {
- struct RastPort *rp = &screen->RastPort;
- short x, y;
-
- /* !!! fix docs! */
- /*
- Line rendering loop.
-
- Loop until all Destination lines have been converted
- (indicated by DstLineNum >= height).
-
- Because the conversion process may introduce an N-line delay
- between source and destination lines, you must call
- CvtDCTVLine() until all the destination lines have been
- converted. That means the code in this loop will be
- executed (height + NDelayLines) times.
-
- Your rendering RGB processing code should use DstLineNum-1
- after converting each line to figure out which RGB line was
- just made.
-
- Since the range of DstLineNum is
- -NDelayLines < DstLineNum <= Height after each call, you need
- to make sure that CvtDCTVLine() actually output a line for you
- to use. If DstLineNum is in the range of
- 0 < DstLineNum <= Height after calling CvtDCTVLine() then a
- line of RGB was just emitted.
- */
-
- /*
- Convert the current line in the RGB line buffer to 4-bit gray by
- extracting just the upper 4 bits of the Blue component.
-
- The caller of this function is expected to avoid calling it for
- DstLineNum values out of range.
-
- The line being displayed is DstLineNum-1 (DstLineNum indicates the
- _next_ line to be output by CvtDCTVLine()).
-
- NOTE: this loop is pathetically slow (mainly due to WritePixel()),
- but is sufficient for this example.
- */
-
- SetDrMd (rp, JAM1);
-
- for (x = 0; x < screen->Width; x++) {
- /* Abort on Ctrl-C. */
- if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) return FALSE;
-
- for (y = 0; y < screen->Height; y++) {
- SetAPen (rp, (ReadDCTVPixel (cvt, x, y) & 0xf0) >> 4); /* get upper 4 bits of blue */
- WritePixel (rp, x, y);
- }
- }
-
- return TRUE;
- }
-
- #else
-
- /* display gradient using CvtDCTVLine() */
-
- void rendergrayline (struct RastPort *, struct DCTVCvtHandle *);
-
- BOOL rendergrayscreen (struct Screen *screen, struct DCTVCvtHandle *cvt)
- {
- /*
- Line rendering loop.
-
- Loop until all Destination lines have been converted
- (indicated by DstLineNum >= height).
-
- Because the conversion process may introduce an N-line delay
- between source and destination lines, you must call
- CvtDCTVLine() until all the destination lines have been
- converted. That means the code in this loop will be
- executed (height + NDelayLines) times.
-
- Your rendering RGB processing code should use DstLineNum-1
- after converting each line to figure out which RGB line was
- just made.
-
- Since the range of DstLineNum is
- -NDelayLines < DstLineNum <= Height after each call, you need
- to make sure that CvtDCTVLine() actually output a line for you
- to use. If DstLineNum is in the range of
- 0 < DstLineNum <= Height after calling CvtDCTVLine() then a
- line of RGB was just emitted.
- */
-
- while (cvt->DstLineNum < cvt->Height) {
-
- /* Abort on Ctrl-C. */
- if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) return FALSE;
-
- CvtDCTVLine (cvt); /* Convert the line in the line buffer to
- DCTV display data. Results in rendering
- a line of the BitMap. */
-
- /* Display 4-bit gray from 24-bit RGB.
- This draws directly to the Screen's Rastport. */
- if (cvt->DstLineNum > 0)
- rendergrayline (&screen->RastPort, cvt);
- }
-
- return TRUE;
- }
-
- void rendergrayline (struct RastPort *rp, struct DCTVCvtHandle *cvt)
- {
- short x;
- short y = cvt->DstLineNum - 1; /* after call, subtract 1 for line just emitted */
-
- /*
- Convert the current line in the RGB line buffer to 4-bit gray by
- extracting just the upper 4 bits of the Blue component.
-
- The caller of this function is expected to avoid calling it for
- DstLineNum values out of range.
-
- The line being displayed is DstLineNum-1 (DstLineNum indicates the
- _next_ line to be output by CvtDCTVLine()).
-
- NOTE: this loop is pathetically slow (mainly due to WritePixel()),
- but is sufficient for this example.
- */
-
- SetDrMd (rp, JAM1);
-
- for (x = 0; x < cvt->Width; x++) {
- SetAPen (rp, cvt->Blue[x] >> 4);
- WritePixel (rp, x, y);
- }
- }
-
- #endif
-
-
- /* -------------------- bitmap allocator */
-
- struct BitMap *allocbm (UWORD width, UWORD height, UBYTE depth)
- {
- ULONG memsize;
- PLANEPTR *ras;
- struct BitMap *bm;
-
- if (depth > 8) goto clean;
-
- if (!(bm = AllocMem (sizeof *bm, MEMF_ANY | MEMF_CLEAR))) goto clean;
- InitBitMap (bm, depth, width, height);
-
- memsize = (ULONG)bm->Rows * bm->BytesPerRow;
- for (ras=bm->Planes; depth--;) {
- if (!(*ras++ = AllocMem (memsize, MEMF_ANY | MEMF_CLEAR))) goto clean;
- }
-
- return bm;
-
- clean:
- if (bm) freebm (bm);
- return NULL;
- }
-
- void freebm (struct BitMap *bm)
- {
- ULONG rassize = (ULONG)bm->Rows * bm->BytesPerRow;
- PLANEPTR *ras;
- short i;
-
- for (ras = bm->Planes, i = bm->Depth; i--; ras++) {
- if (*ras) {
- FreeMem (*ras, rassize);
- *ras = NULL;
- }
- }
- FreeMem (bm, sizeof *bm);
- }
-
-
- /* -------------------- 24-bit RGB gradient functions */
-
- #define gcent(m,l) (((m)-(l)) / 2) /* centering macro */
-
- void initgrad (struct DCTVCvtHandle *cvt)
- {
- short bufwidth = cvt->Width;
- short imagewidth = cvt->ImageBounds.MaxX - cvt->ImageBounds.MinX + 1;
- short i;
-
- /* init line to black */
- memset (cvt->Red, 0, bufwidth);
- memset (cvt->Green, 0, bufwidth);
- memset (cvt->Blue, 0, bufwidth);
-
- /* ramp red horizontally */
- for (i=0; i < imagewidth; i++)
- cvt->Red [i+cvt->ImageBounds.MinX] = (ULONG)i * 255 / imagewidth;
- }
-
- void rendergradline (struct DCTVCvtHandle *cvt)
- {
- short imagewidth = cvt->ImageBounds.MaxX - cvt->ImageBounds.MinX + 1;
- short imageheight = cvt->ImageBounds.MaxY - cvt->ImageBounds.MinY + 1;
- short y = cvt->SrcLineNum - cvt->ImageBounds.MinY;
- short bluewidth;
- UBYTE greenval;
-
- if (y >= 0 && y < imageheight) {
- /* constant green component for line */
- greenval = (long)y * 255 / imageheight;
- memset (cvt->Green + cvt->ImageBounds.MinX, greenval, imagewidth);
-
- /* reverse wedge blue component */
- bluewidth = (long)(imageheight - y) * imagewidth / imageheight;
- if (bluewidth > 0)
- memset (cvt->Blue + gcent (imagewidth, bluewidth) + cvt->ImageBounds.MinX, 255-greenval, bluewidth);
- }
- }
-